'''
* This is the projet for Brtc LlmOps Platform
* @Author Leon-liao <liaosiliang@alltman.com>
* @Description //TODO 
* @File: openapi_schema.py
* @Time: 2025/11/11
* @All Rights Reserve By Brtc
'''
from enum import Enum

from openai import BaseModel
from pydantic import Field, field_validator
from internal.exception.exception import ValidateErrorException

class ParameterType(str, Enum):
    """参数支持的类型"""
    STR:str = "str"
    INT:str = "int"
    FLOAT:str = "float"
    BOOL:str = "bool"


class ParameterIn(str, Enum):
    """参顺支持存放的位置"""
    PATH:str = "path"
    QUERY:str = "query"
    HEADER:str = "header"
    COOKIE:str = "cookie"
    REQUEST_BODY:str = "body"

ParameterTypeMap = {
    ParameterType.STR: str,
    ParameterType.INT: int,
    ParameterType.FLOAT: float,
    ParameterType.BOOL: bool,
}


class OpenAPISchema(BaseModel):
    """OpenApi 的数据规范"""
    server:str = Field(default="", validate_default=True, description="工具提供者的服务基础地址")
    description:str = Field(default="", validate_default=True, description="工具提供者的描述信息")
    paths:dict[str, dict] = Field(default_factory=dict, validate_default=True, description="工具提供者的路径参数字典")

    @field_validator("server", mode="before")
    def validate_server(cls,server:str)->str:
        """校验sever 数据"""
        if server is None or server == "":
            raise ValidateErrorException("server 不能为空且为字符串！！")
        return server

    @field_validator("description", mode="before")
    def validate_description(cls,description:str)->str:
        """校验description信息"""
        if description is None or description == "":
            raise ValidateErrorException("description 不能为空且为字符串！")
        return description

    @field_validator("paths", mode="before")
    def validate_paths(cls,paths:dict[str, dict])->dict[str, dict]:
        """校验paths, 涵盖方法提取、 operationId 唯一标识、 parameters 校验"""
        #1、paths 不能为空且为字典
        if not paths or not isinstance(paths, dict):
            raise ValidateErrorException("openapi_schema 中的 paths 不能为空且必须为字典！")
        #2、提取paths 里面的每一个元素，并获取元素下的get/post方法
        methods = ["get", "post"]
        interfaces = []
        extra_paths = {}
        for path , path_items in paths.items():
            for method in methods:
                #3、检测是否存在特定的方法并提取信息
                if method in path_items:
                    interfaces.append({
                        "path": path,
                        "method": method,
                        "operation": path_items[method]
                    })
        #4、遍历提取到的所有接口并校验信息， 涵盖operationId 唯一标识, parameters 参数
        operation_ids = []
        for interface in interfaces:
            #5、校验description/operationId/parameters参数
            if not isinstance(interface["operation"].get("description"), str):
                raise ValidateErrorException("description 不能为空且必须是字符串！！")
            if not isinstance(interface["operation"].get("operationId"), str):
                raise ValidateErrorException("operationId 不能为空且必须是字符串！！")
            if not isinstance(interface["operation"].get("parameters",[]), list):
                raise ValidateErrorException("parameters 不能为空且必须是列表！！")

            #6、检测operationId 是否唯一
            if interface["operation"]["operationId"] in operation_ids:
                raise ValidateErrorException(f"operationId必须是唯一的 {interface['operation']['operationId']}已经存在！")
            operation_ids.append(interface["operation"]["operationId"])

            #7、检验parameters参数格式是否正确
            for parameter in interface["operation"].get("parameters", []):
                #8、检验name/in/ description / required /type 参数是否存在，并类型正确
                if not isinstance(parameter.get("name"), str):
                    raise ValidateErrorException("parameters 的 name 必须为字符串！！")

                if not isinstance(parameter.get("description"), str):
                    raise ValidateErrorException("parameters 的 description 必须为字符串！！")

                if not isinstance(parameter.get("required"), bool):
                    raise ValidateErrorException("parameters 的 required 必须为布尔值！！")

                if (
                        not isinstance(parameter.get("in"), str)
                        or  parameter.get("in") not in ParameterIn.__members__.values()
                ):
                    raise ValidateErrorException(f"parameters 的 in 必须为 {'/'.join([item.value for item in ParameterIn])}")


                if (
                        not isinstance(parameter.get("type"), str)
                        or  parameter.get("type") not in ParameterType.__members__.values()
                ):
                    raise ValidateErrorException(f"parameters 的 type 必须为{'/'.join([item.value for item in ParameterType])}！！")
            #9、组装数据并更新
            extra_paths[interface["path"]] = {
                interface["method"]:{
                    "description": interface["operation"]["description"],
                    "operationId": interface["operation"]["operationId"],
                    "parameters": [{
                        "name": parameter.get("name"),
                        "in": parameter.get("in"),
                        "description": parameter.get("description"),
                        "required": parameter.get("required"),
                        "type": parameter.get("type"),
                    } for parameter in interface["operation"].get("parameters", [])]
                }
            }
        return extra_paths






















